package com.vctgo.evidence.controller;

import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletResponse;

import com.vctgo.common.core.utils.StringUtils;
import com.vctgo.evidence.domain.EsEvidence;
import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.vctgo.common.log.annotation.Log;
import com.vctgo.common.log.enums.BusinessType;
import com.vctgo.common.security.annotation.RequiresPermissions;
import com.vctgo.evidence.domain.TbEvidence;
import com.vctgo.evidence.service.ITbEvidenceService;
import com.vctgo.common.core.web.controller.BaseController;
import com.vctgo.common.core.web.domain.AjaxResult;
import com.vctgo.common.core.utils.poi.ExcelUtil;

/**
 * 凭证列表Controller
 *
 * * @author vctgo
 * @date 2024-12-15
 */
@RestController
@RequestMapping("/evidence")
public class TbEvidenceController extends BaseController {
    /**
     *     自动注入凭证服务接口
      */
    @Autowired
    private ITbEvidenceService tbEvidenceService;

    /**
     *     自动注入Elasticsearch模板
      */
    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 创建Elasticsearch索引
     * <p>
     * * 此方法用于创建TbEvidence类对应的Elasticsearch索引，如果索引已存在，则先删除再创建，并设置映射
     * <p>
     * * @return 操作结果
     */
    @GetMapping("/createIndex")
    public AjaxResult createIndex() {
        // 获取TbEvidence类的索引操作对象
        IndexOperations indexOps = elasticsearchRestTemplate.indexOps(TbEvidence.class);
        // 尝试创建索引，若索引已存在则返回true
        boolean esExists = indexOps.create();
        // 若索引已存在，则删除并重新创建
        if (esExists) {
            indexOps.delete();
        }
        // 再次尝试创建索引
        indexOps.create();
        // 创建索引映射
        Document mapping = indexOps.createMapping();
        // 应用索引映射
        indexOps.putMapping(mapping);
        // 返回操作成功的响应
        return success();
    }

    /**
     * 查询凭证列表列表
     * <p>
     * * 该方法用于查询符合条件的凭证列表信息，需要相应权限
     *
     * @param tbEvidence 凭证列表对象，包含查询条件
     * @return 凭证列表信息
     */
    @RequiresPermissions("evidence:evidence:list")
    @GetMapping("/list")
    public AjaxResult list(TbEvidence tbEvidence) {
        // 调用服务层方法查询凭证列表
        List<TbEvidence> tbEvidences = tbEvidenceService.selectTbEvidenceList(tbEvidence);
        // 返回查询结果
        return success(tbEvidences);
    }

    /**
     * 使用Elasticsearch查询凭证列表
     * <p>
     * * 该方法通过Elasticsearch查询凭证信息，支持分页和高亮显示
     *
     * @param tbEvidence 凭证列表对象，包含查询条件
     * @return 查询结果，包括总命中数和凭证列表
     */
    @GetMapping("/esList")
    public AjaxResult esList(TbEvidence tbEvidence) {
        // 创建NativeSearchQueryBuilder实例
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

        // 初始化分页页码，默认为0
        Integer pageNumber = 0;
        // 根据传入的pageNum调整实际页码
        if (tbEvidence.getPageNum() > 0) {
            pageNumber = tbEvidence.getPageNum() - 1;
        }
        // 创建分页请求对象
        PageRequest pageRequest = PageRequest.of(pageNumber, tbEvidence.getPageSize());
        // 创建布尔查询构建器
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 添加查询条件，匹配摘要、会计科目和备注字段
        if (!StringUtils.isEmpty(tbEvidence.getDigest())) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("digest", tbEvidence.getDigest()));
            boolQueryBuilder.must(QueryBuilders.matchQuery("accountingSubject", tbEvidence.getAccountingSubject()));
            boolQueryBuilder.must(QueryBuilders.matchQuery("remark", tbEvidence.getRemark()));
        }
        // 高亮设置
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        // 设置摘要字段高亮样式
        highlightBuilder.field("digest").preTags("<font color ='red'>").postTags("</font>");
        // 设置会计科目字段高亮样式
        highlightBuilder.field("accountingSubject").preTags("<font color ='red'>").postTags("</font>");
        // 设置备注字段高亮样式
        highlightBuilder.field("remark").preTags("<font color ='red'>").postTags("</font>");

        // 构建查询请求，应用查询条件、高亮设置和分页请求
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder).withHighlightBuilder(highlightBuilder).withPageable(pageRequest);
        // 执行搜索查询
        SearchHits<EsEvidence> search = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), EsEvidence.class);
        // 获取总命中数
        long totalHits = search.getTotalHits();
        // 创建结果列表
        ArrayList<EsEvidence> rows = new ArrayList<>();
        // 遍历搜索结果
        for (SearchHit<EsEvidence> searchHit : search.getSearchHits()) {
            // 获取当前命中的内容
            EsEvidence content = searchHit.getContent();
            // 获取摘要字段的高亮内容
            List<String> digest = searchHit.getHighlightField("digest");
            // 获取会计科目字段的高亮内容
            List<String> accountingSubject = searchHit.getHighlightField("accountingSubject");
            // 设置高亮后的摘要内容
            content.setDigest(digest.get(0));
            // 设置高亮后的会计科目内容
            content.setAccountingSubject(accountingSubject.get(0));
            // 将处理后的内容添加到结果列表
            rows.add(content);
        }
        // 返回查询结果，包括状态码、消息、总命中数和结果列表
        return new AjaxResult(200, "查询成功", totalHits, rows);
    }

    /**
     * 导出凭证列表列表
     * <p>
     * * 该方法用于导出符合条件的凭证列表信息至Excel文件，需要相应权限
     *
     * @param response   HTTP响应对象，用于输出Excel文件流
     * @param tbEvidence 凭证列表对象，包含查询条件
     */
    @RequiresPermissions("evidence:evidence:export")
    @Log(title = "凭证列表", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, TbEvidence tbEvidence) {
        // 查询符合条件的凭证列表
        List<TbEvidence> list = tbEvidenceService.selectTbEvidenceList(tbEvidence);
        // 创建Excel工具类实例
        ExcelUtil<TbEvidence> util = new ExcelUtil<TbEvidence>(TbEvidence.class);
        // 导出Excel文件
        util.exportExcel(response, list, "凭证列表数据");
    }

    /**
     * 获取凭证列表详细信息
     * <p>
     * * 该方法用于获取指定ID的凭证详细信息
     *
     * @param id 凭证ID
     * @return 凭证详细信息
     */
    //    @RequiresPermissions("evidence:evidence:query")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        // 调用服务层方法获取凭证详情
        return success(tbEvidenceService.selectTbEvidenceById(id));
    }

    /**
     * 新增凭证列表
     * <p>
     * * 该方法用于新增凭证记录，需要相应权限
     *
     * @param tbEvidence 待新增的凭证对象
     * @return 操作结果
     */
    @RequiresPermissions("evidence:evidence:add")
    @Log(title = "凭证列表", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody TbEvidence tbEvidence) {
        // 调用服务层方法插入凭证记录
        return toAjax(tbEvidenceService.insertTbEvidence(tbEvidence));
    }

    /**
     * 修改凭证列表
     * <p>
     * * 该方法用于修改指定ID的凭证记录，需要相应权限
     *
     * @param tbEvidence 待更新的凭证对象
     * @return 操作结果
     */
    @RequiresPermissions("evidence:evidence:edit")
    @Log(title = "凭证列表", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody TbEvidence tbEvidence) {
        // 调用服务层方法更新凭证记录
        return toAjax(tbEvidenceService.updateTbEvidence(tbEvidence));
    }

    /**
     * 删除凭证列表
     * <p>
     * * 该方法用于删除指定ID的凭证记录，需要相应权限
     *
     * @param ids 待删除的凭证ID数组
     * @return 操作结果
     */
    @RequiresPermissions("evidence:evidence:remove")
    @Log(title = "凭证列表", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        // 调用服务层方法删除凭证记录
        return toAjax(tbEvidenceService.deleteTbEvidenceByIds(ids));
    }



}





